如果你是一位偵探,在法庭上指著一名嫌疑犯說:「根據我的 AI 監視器分析,這個人在案發當時出現在現場,有 99% 的嫌疑!」
法官敲了敲木槌說:「推理很精彩,但過去的法律文獻與判例庫裡,有沒有記載過類似的犯罪手法?有沒有其他檢察官發表過的鑑定報告?」
在臨床醫學與基因診斷的世界裡也是一樣的!
但對謹慎的醫生來說,單憑 AI 的預測還是不夠。醫生需要看到權威醫學期刊(如 Nature、Cell、NEJM 或全球最大生醫論文庫 PubMed)上是否有其他醫學團隊發表過同一個基因變異的真實病例報告!
使用 「文獻檢索代理人(Literature Agent)」,透過 Function Calling(函式呼叫) 技術,讓 AI 自動拿著遙控器去搜尋 PubMed,讓我們的診斷報告補上鐵證如山的學術實證鏈!
大語言模型(LLM)雖然知識淵博,但它受限於訓練資料的時間截止點,且有時會產生「幻覺(Hallucination)」——憑空捏造看似真實但根本不存在的論文題目與作者。
在嚴肅的醫療領域,絕對不能讓 AI 瞎編論文!
為了解決這個問題,Google 提供了 Function Calling(函式呼叫) 機制。這就像是我們給 AI 一把全球生醫圖書館(PubMed)的數位鑰匙:
chr9:128225994:G>A)時,它知道自己需要最新的同毒性論文佐證。DNM1 epileptic encephalopathy splicing 去 PubMed 搜尋最新的 3 篇論文摘要!」| 檢索方式 | 傳統人工搜尋 | 傳統 AI 聊天 (無 Function Calling) | AI+ PubMed Function Calling |
|---|---|---|---|
| 搜尋速度 | 醫生手動打開 PubMed 敲關鍵字,耗時 30 分鐘以上。 | 幾秒鐘回覆,但可能胡亂捏造不存在的論文。 | 秒速自動搜尋,且 100% 來自 PubMed 真實文獻! |
| 資料真實性 | 100% 真實,但耗費大量精力。 | 低(存在 AI 幻覺風險)。 | 100% 精準核對,帶有 PMID 與 DOI 論文連結。 |
| 系統整合度 | 無法與基因數據結合,需人工比對。 | 文字散亂,無法結構化。 | 自動與 AlphaGenome AVI 分數結合,直接輸出完整診斷鏈! |
PubMed 是由美國國家生物技術資訊中心(NCBI)維護的全球最大免費生物醫學論文資料庫,收錄了超過 3,500 萬篇 生醫期刊文獻。
NCBI 官方提供了名為 Entrez API 的程式串接管道:
esearch(搜尋):輸入關鍵字(如基因名稱 + 疾病),回傳符合條件的論文 ID 清單(PMID)。esummary / efetch(摘要):輸入 PMID,抓取該篇論文的題目、作者、出版年份與完整摘要(Abstract)。我們的 Literature Agent 就是將 Entrez API 包裝成一個 Python 函數,讓 AI 在需要時隨時調用!
pubmed_literature_agent.py)打開程式碼編輯器,建立 Python 腳本 pubmed_literature_agent.py。我們使用 Google GenAI SDK 的 Function Calling 功能,示範如何讓 AI 自動搜尋 PubMed:
import os
import json
import urllib.request
import urllib.parse
from dotenv import load_dotenv
import google.generativeai as genai
# 載入隱藏設定檔中的 Gemini API Key
load_dotenv()
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
# 1. 定義讓 Gemini 調用的實體工具函數:搜尋 PubMed 論文
def search_pubmed_literature(gene_symbol: str, condition_keyword: str) -> str:
"""
透過 NCBI Entrez API 搜尋 PubMed 資料庫中關於特定基因與疾病的最新論文摘要。
:param gene_symbol: 基因名稱,例如 'DNM1' 或 'SCN1A'
:param condition_keyword: 疾病或機制關鍵字,例如 'epilepsy' 或 'splicing'
:return: 回傳格式化的最新 2 篇論文題目與摘要 JSON
"""
query = f"{gene_symbol} AND {condition_keyword}"
encoded_query = urllib.parse.quote(query)
print(f"🌐 [Tool Call] 正在連線 PubMed 搜尋關鍵字: '{query}' ...")
try:
# 步驟 A: 呼叫 esearch 獲取 PMID 清單
search_url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term={encoded_query}&retmode=json&retmax=2"
req = urllib.request.Request(search_url, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req) as response:
search_data = json.loads(response.read().decode())
pmid_list = search_data.get('esearchresult', {}).get('idlist', [])
if not pmid_list:
return json.dumps({"status": "NO_RESULTS", "message": "PubMed 中未找到相關文獻。"})
# 步驟 B: 呼叫 esummary 獲取論文詳細資訊
ids_str = ",".join(pmid_list)
summary_url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id={ids_str}&retmode=json"
req = urllib.request.Request(summary_url, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req) as response:
summary_data = json.loads(response.read().decode()).get('result', {})
articles = []
for pmid in pmid_list:
item = summary_data.get(pmid, {})
articles.append({
"pmid": pmid,
"title": item.get('title', ''),
"source": item.get('source', ''),
"pubdate": item.get('pubdate', '')
})
return json.dumps({"status": "SUCCESS", "articles": articles}, ensure_ascii=False)
except Exception as e:
return json.dumps({"status": "ERROR", "error": str(e)})
# 2. 設定 Gemini Agent 模型並註冊 Function Calling 工具
tools_list = [search_pubmed_literature]
model = genai.GenerativeModel(
model_name="gemini-1.5-pro",
tools=tools_list, # 將 PubMed 搜尋工具掛載給 Gemini
system_instruction="""
你是一位罕見病基因文獻檢索 Agent。
當使用者詢問某個基因變異與疾病時,你必須【主動呼叫 search_pubmed_literature 工具】檢索最新的真實論文。
拿到論文數據後,請摘要出文獻證據,並明確標註 PMID 編號。嚴禁憑空幻想論文標題或 PMID!
"""
)
if __name__ == "__main__":
# 開啟支援 Function Calling 的對話 Session
chat = model.start_chat(enable_automatic_function_calling=True)
user_query = "請幫我檢索關於 DNM1 基因在癲癇 (epilepsy) 與異常剪接方面的 PubMed 文獻證據。"
print(f"👤 使用者提問: {user_query}\n")
# 傳送提問,Gemini 會自動決定觸發 Tool Call 呼叫 PubMed API
response = chat.send_message(user_query)
print("\n" + "="*50)
print("🤖 Gemini Literature Agent 回覆報告:")
print(response.text)
print("="*50 + "\n")
執行這段腳本時,你會在終端機看到 Gemini 自動觸發了 search_pubmed_literature 工具,去 NCBI 網站抓回真實的 PMID 與論文標題(例如關於 DNM1 隱藏剪接與癲癇性腦病變的文獻),並輸出帶有真實 PMID 證明的學術報告!
有了數據、推理與文獻後,我們要如何讓系統輸出符合國際權威 ACMG/AMP(美國醫學遺傳學會) 臨床指引的變異致病性分類(如 Pathogenic, Likely Pathogenic, VUS)呢?
之後將會開始 「ACMG/AMP 臨床等級自動評估與 Antigravity 多代理(Multi-Agent)架構整合」,如何讓多個 AI 代理人分工協作,打造真正醫院臨床等級的終極診斷系統!